from abc import ABCMeta, abstractmethod


# 状态模式关键在于找到使状态发生改变的某个属性或某个某个属性集，比如水的状态的改变关键在于温度
class Context(metaclass=ABCMeta):
    """状态类的上下文环境类"""
    def __init__(self):
        self.__states = []
        self.__curState = None
        # 状态发生变化依赖的属性，当这个一变量有多个共同决定时可以将其单独定义为一个类
        self.__stateInfo = 0

    def addState(self, state):
        if state not in self.__states:
            self.__states.append(state)

    def changeState(self, state):
        if state is None:
            return False
        if self.__curState is None:
            print("初始化为", state.getName())
        else:
            print("由", self.__curState.getName(), "变为", state.getName())
        self.__curState = state
        self.addState(state)
        return True

    def getState(self):
        return self.__curState

    def _setStateInfo(self, stateInfo):
        self.__stateInfo = stateInfo
        for state in self.__states:
            if state.isMatch(stateInfo):
                self.changeState(state)

    def _getStateInfo(self):
        return self.__stateInfo

    def behavior(self):
        state = self.getState()
        if isinstance(state, State):
            state.behavior(self)



class State:
    "状态的基类"
    def __init__(self, name):
        self.__name = name

    def getName(self):
        return self.__name

    def isMatch(self, stateInfo):
        "状态的属性stateInfo是否在当前的状态范围内"
        return False

    @abstractmethod
    def behavior(self, context):
        pass


class Water(Context):
    def __init__(self):
        super().__init__()
        self.addState(SolidState("固态"))
        self.addState(LiquidState("液态"))
        self.addState(GaseousState("气态"))
        self.setTemperature(25)
    
    def getTemperature(self):
        return self._getStateInfo()

    def setTemperature(self, temperature):
        self._setStateInfo(temperature)

    def riseTemperature(self, step):
        self.setTemperature(self.getTemperature()+step)

    def reduceTemperature(self, step):
        self.setTemperature(self.getTemperature()-step)



class SolidState(State):
    def __init__(self, name):
        super().__init__(name)

    def isMatch(self, stateInfo):
        return stateInfo < 0

    def behavior(self, context):
        print("我性格高冷，当前体温", context._getStateInfo(), "C，我坚硬如铁，放入一冷血动物，请用我砸人，嘿嘿......")


class LiquidState(State):
    def __init__(self, name):
        super().__init__(name)

    def isMatch(self, stateInfo):
        return stateInfo >= 0 and stateInfo < 100

    def behavior(self, context):
        print("我性格温和，当前体温", context._getStateInfo(), "C，我可滋润万物，饮用我可让你活力倍增......")


class GaseousState(State):
    def __init__(self, name):
        super().__init__(name)

    def isMatch(self, stateInfo):
        return stateInfo >= 100

    def behavior(self, context):
        print("我性格热烈，当前体温", context._getStateInfo(), "C，飞向天空是我毕生的梦想，在这你将看不到我的存在，我将达到无我的境界......")


if __name__ == "__main__":
    water = Water()
    water.setTemperature(40)
    water.behavior()







    